Conversation
initialized on their first call and return a reference to it; avoids static initialization order fiasco) instead of pointers allocated on demand. Use std::shared_ptr for LoadedLibraries loaded libraries so that libraries and aliases can share the same loader pointers without memory leaks. Use C++17 "inline" with static const members so that they can be initialized in-class and won't have multiple definition errors if defined in a header.
|
CLANG-FORMAT TEST - PASSED |
|
CMAKE-FORMAT TEST - PASSED |
| for ( auto& elempair : libpair.second ) { | ||
| // loop all the loaders in the element | ||
| for ( auto* loader : elempair.second ) { | ||
| for ( auto& loader : elempair.second ) { |
There was a problem hiding this comment.
This allows loader to be either a regular pointer or a smart pointer. The previous code only allowed regular pointers.
| return iter->second; | ||
| } | ||
| } | ||
| BaseBuilder* getBuilder(const std::string& name) { return factories_[name]; } |
There was a problem hiding this comment.
Since I do not see anywhere factories_ is used in such a way that adding nullptr entries would be a problem, this function can simply reduced to this subscript operator, which will create and return a nullptr entry if the name doesn't exist.
| static Map libraries; // Database | ||
| auto& lib = libraries[name]; | ||
| if ( !lib ) lib = new Library(name); | ||
| return lib; |
There was a problem hiding this comment.
This is the Meyers singleton initializing the map on the first call to getLibrary().
It also uses a reference to the map entry and checks if it's nullptr, and if it is (such as if it did not exist before), sets it to allocated memory.
| static bool isLoaded() { return loaded; } | ||
|
|
||
| static const bool loaded; | ||
| static inline const bool loaded = Base::Ctor::template add<T>(); |
There was a problem hiding this comment.
inline can be used with static class data members in C++17, and they can be initialized in-class. This prevents multiple definitions which could occur in the old code if the variable was ODR-used (had its address taken), since it was defined in the header file.
static constexpr member variables are inline by default, but the initializer here is not constexpr (it possibly could be made so, if the operator() and its return value were constexpr).
src/sst/core/eli/elementbuilder.h
Outdated
| if ( !cached_ ) { cached_ = new T(std::forward<Args>(ctorArgs)...); } | ||
| return cached_; | ||
| static T cached(std::forward<Args>(ctorArgs)...); | ||
| return &cached; |
There was a problem hiding this comment.
Another Meyers Singleton, in lieu of calling new if a pointer is nullptr (I did not see this CachedAllocator used anywhere, and I doubt any code calls delete on its returned address, so returning the address of a static is okay).
There was a problem hiding this comment.
If it needs to be a pointer which can be deleted, it simply needs to be changed to:
static T* cached = new T(std::forward<Args>(ctorArgs)...);
return cached;| { | ||
| static std::map<std::string, std::map<std::string, T*>> infos_; | ||
| return infos_; | ||
| } |
There was a problem hiding this comment.
Another Meyers singleton.
| { | ||
| static Map libs; | ||
| return libs; | ||
| } |
| if ( !alias.empty() ) (*loaders_)[lib][alias].push_back(loader); | ||
| return true; | ||
| } | ||
| std::shared_ptr<LibraryLoader> shared_loader(loader); |
There was a problem hiding this comment.
We create a std::shared_ptr which owns the loader pointer passed in.
| } | ||
| auto& library = getLoaders()[lib]; | ||
| if ( !alias.empty() && alias != name ) library[alias].push_back(shared_loader); | ||
| library[name].push_back(std::move(shared_loader)); |
There was a problem hiding this comment.
On the last use of shared_loader we use std::move() so that it doesn't have the overhead of incrementing the reference count during the push_back() and then decrementing the reference count when shared_loader is destroyed. We move shared_loader to the new entry without changing reference counts, and its destruction is a no-op.
| { | ||
| public: | ||
| using InfoMap = std::map<std::string, std::list<LibraryLoader*>>; | ||
| using InfoMap = std::map<std::string, std::deque<std::shared_ptr<LibraryLoader>>>; |
There was a problem hiding this comment.
std::deque is faster than std::list and std::vector for adding an unknown number of items repeatedly to the end of a list which grows. std::list requires more dynamic memory allocations and is cache-unfriendly, and std::vector requires moving the entire vector's data to a new location if it has to increase its capacity. std::deque is also randomly accessible like std::vector, but it's not contiguous. I would look at all places std::vector and std::list are used and see if std::deque might be better.
| { | ||
| static LibraryMap loaders; | ||
| return loaders; | ||
| } |
There was a problem hiding this comment.
Meyers singleton.
|
Status Flag 'Pre-Test Inspection' - - This Pull Request Requires Inspection... The code must be inspected by a member of the Team before Testing/Merging |
|
@leekillough poke for rebase |
|
Status Flag 'Pre-Test Inspection' - - This Pull Request Requires Inspection... The code must be inspected by a member of the Team before Testing/Merging |
|
CMAKE-FORMAT TEST - PASSED |
|
Status Flag 'Pre-Merge Inspection' - - This Pull Request Requires Inspection... The code must be inspected by a member of the Team before Testing/Merging |
|
All Jobs Finished; status = PASSED, However Inspection must be performed before merge can occur... |
|
CLANG-FORMAT TEST - PASSED |
|
CMAKE-FORMAT TEST - PASSED |
|
Status Flag 'Pre-Test Inspection' - - This Pull Request Requires Inspection... The code must be inspected by a member of the Team before Testing/Merging |
|
CLANG-FORMAT TEST - PASSED |
|
CMAKE-FORMAT TEST - PASSED |
|
Status Flag 'Pre-Test Inspection' - SUCCESS: The last commit to this Pull Request has been INSPECTED by label AT: PRE-TEST INSPECTED! Autotester is Removing Label; this inspection will remain valid until a new commit to source branch is performed. |
|
Status Flag 'Pull Request AutoTester' - Testing Jenkins Projects: Pull Request Auto Testing STARTING (click to expand)Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_OMPI-4.1.4_PY3.6_sst-elements
Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_OMPI-4.1.4_PY3.6_sst-elements_MR-2
Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_OMPI-4.1.4_PY3.6_sst-elements_MT-2
Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_OMPI-4.1.4_PY3.6_sst-macro_withsstcore
Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_OMPI-4.1.4_PY3.6_sst-core_Make-Dist
Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_Clang-Format_sst-core
Build InformationTest Name: SST__AutotestGen2_NewFW_OSX-14-XC15-ARM2_OMPI-4.1.6_PY3.10_sst-elements
Build InformationTest Name: SST__AutotestGen2_NewFW_OSX-14-XC15-ARM2_OMPI-4.1.6_PY3.10_sst-macro_withsstcore
Using Repos:
Pull Request Author: leekillough |
|
Status Flag 'Pull Request AutoTester' - Jenkins Testing: all Jobs PASSED Pull Request Auto Testing has PASSED (click to expand)Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_OMPI-4.1.4_PY3.6_sst-elements
Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_OMPI-4.1.4_PY3.6_sst-elements_MR-2
Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_OMPI-4.1.4_PY3.6_sst-elements_MT-2
Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_OMPI-4.1.4_PY3.6_sst-macro_withsstcore
Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_OMPI-4.1.4_PY3.6_sst-core_Make-Dist
Build InformationTest Name: SST__AutotestGen2_NewFW_sst-test_Clang-Format_sst-core
Build InformationTest Name: SST__AutotestGen2_NewFW_OSX-14-XC15-ARM2_OMPI-4.1.6_PY3.10_sst-elements
Build InformationTest Name: SST__AutotestGen2_NewFW_OSX-14-XC15-ARM2_OMPI-4.1.6_PY3.10_sst-macro_withsstcore
|
|
Status Flag 'Pre-Merge Inspection' - SUCCESS: The last commit to this Pull Request has been INSPECTED AND APPROVED by [ feldergast ]! |
|
Status Flag 'Pull Request AutoTester' - Pull Request MUST BE MERGED MANUALLY BY Project Team - This Repo does not support Automerge |
* Use Meyers singletons (static variables local to functions which are initialized on their first call and return a reference to it; avoids static initialization order fiasco) instead of pointers allocated on demand. Use std::shared_ptr for LoadedLibraries loaded libraries so that libraries and aliases can share the same loader pointers without memory leaks. Use C++17 "inline" with static const members so that they can be initialized in-class and won't have multiple definition errors if defined in a header.
Use Meyers Singletons (
staticvariables local to functions which are initialized on their first call and return a reference to it; avoidsstaticinitialization order fiasco) instead of pointers allocated on demand.Use
std::shared_ptrforLoadedLibrariesloaded libraries so that libraries and aliases can share the same loader pointers without memory leaks. I was prompted to do this byvalgrind:I can see other places where
std::shared_ptrandstd::unique_ptrshould be used, but since the memory system is being overhauled, I won't touch the other places.inlinewithstatic constclass members so that they can be defined in-class and won't have multiple definition errors if defined in a header.